using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ComponentSystem;
using Cysharp.Threading.Tasks;
using UnityEngine;

namespace ZYFramework.ObjectPool
{
    public partial class PoolManager_Entity : EntityCSharp
    {
        /// <summary>
        /// 单例实例
        /// </summary>
        public static PoolManager_Entity _instance;

        /// <summary>
        /// 默认关键字（空字符串表示默认池，用于向后兼容）
        /// </summary>
        private const string DefaultKey = "default";

        protected UnityEngine.GameObject _poolRoot;
        public UnityEngine.GameObject PoolRoot { get { return _poolRoot; } }

        #region 缓存表

        /// <summary>
        /// 对象池映射表（按类型和关键字嵌套存储）
        /// </summary>
        private readonly Dictionary<Type, Dictionary<string, object>> _pools = new Dictionary<Type, Dictionary<string, object>>();

        #endregion

        #region 事件

        /// <summary>
        /// 池创建事件
        /// </summary>
        public event Action<Type> OnPoolCreated;

        /// <summary>
        /// 池销毁事件
        /// </summary>
        public event Action<Type> OnPoolDestroyed;

        /// <summary>
        /// 全局回收事件
        /// </summary>
        public event Action OnGlobalRecycle;

        #endregion
    }

    public partial class PoolManager_Entity
    {
        public PoolManager_Entity()
        {
            if (_instance != null)
            {
                Debug.LogError("PoolManager_Entity 单例已存在");
                return;
            }

            this.Constructor();
            _instance = this;
            _poolRoot = new UnityEngine.GameObject("PoolManager_Entity");
            UnityEngine.Object.DontDestroyOnLoad(_poolRoot);
        }

        /// <summary>
        /// 注册对象池（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="config">池配置</param>
        public IObjectPool<T> RegisterPool<T>(ObjectPoolConfig<T> config)
        {
            return RegisterPool<T>(DefaultKey, config);
        }

        /// <summary>
        /// 注册对象池（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字，用于区分同一类型的不同对象池</param>
        /// <param name="config">池配置</param>
        public IObjectPool<T> RegisterPool<T>(string key, ObjectPoolConfig<T> config)
        {
            if (config == null) throw new ArgumentNullException(nameof(config));

            var type = typeof(T);
            var normalizedKey = NormalizeKey(key);

            // 确保类型字典存在
            if (!_pools.TryGetValue(type, out var keyPools))
            {
                keyPools = new Dictionary<string, object>();
                _pools[type] = keyPools;
            }

            // 检查该关键字的池是否已存在
            if (keyPools.ContainsKey(normalizedKey))
            {
                throw new InvalidOperationException($"缓存池类型 {type.Name} 关键字 '{normalizedKey}' 已存在");
            }

            // 创建对象池
            IObjectPool<T> pool;
            string poolName = string.IsNullOrEmpty(normalizedKey) ? DefaultKey : normalizedKey;
            pool = (IObjectPool<T>)(object)new Com_ObjectPool<T>((ObjectPoolConfig<T>)(object)config, $"{type.Name}/{poolName}", _poolRoot);

            keyPools[normalizedKey] = pool;

            OnPoolCreated?.Invoke(type);

            return pool;
        }

        #region 对象操作

        /// <summary>
        /// 获取对象（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="priority">优先级</param>
        /// <returns>对象</returns>
        public T Get_Sync<T>()
        {
            return Get_Sync<T>(DefaultKey);
        }

        /// <summary>
        /// 获取对象（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="priority">优先级</param>
        /// <returns>对象</returns>
        public T Get_Sync<T>(string key)
        {

            var pool = GetPool<T>(key);
            var obj = pool.Get_Sync();

            return obj;
        }

        /// <summary>
        /// 异步获取对象（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="priority">优先级</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>对象</returns>
        public async UniTask<T> Get_Async<T>(CancellationToken cancellationToken = default)
        {
            return await Get_Async<T>(DefaultKey, cancellationToken);
        }

        /// <summary>
        /// 异步获取对象（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="priority">优先级</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>对象</returns>
        public async UniTask<T> Get_Async<T>(string key, CancellationToken cancellationToken = default)
        {
            var pool = GetPool<T>(key);
            var obj = await pool.Get_Async(cancellationToken);

            return obj;
        }

        /// <summary>
        /// 释放对象（使用默认关键字，向后兼容）
        /// 如果对象不在默认池中，会自动查找对象所属的池并释放
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">要释放的对象</param>
        public void Release_Sync<T>(T obj)
        {
            if (obj == null) return;

            // 先尝试默认池
            string normalizedKey = NormalizeKey(DefaultKey);
            IObjectPool<T> pool = GetPool<T>(normalizedKey);

            // 检查对象是否在指定的池中
            bool isInActivePool = pool.IsObjectInActivePool(obj);

            if (isInActivePool)
            {
                // 对象在指定池中，直接释放
                pool.Release_Sync(obj);
            }
            else
            {
                // 对象不在指定池中，尝试查找实际所属的池
                if (TryFindPoolForObject(obj, out var foundPool))
                {
                    foundPool.Release_Sync(obj);
                }
                else
                {
                    Debug.LogError($"对象 {typeof(T).Name} 不在活跃池中,本次释放无效");
                }
            }
        }

        /// <summary>
        /// 释放对象（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="obj">要释放的对象</param>
        public void Release_Sync<T>(string key, T obj)
        {
            if (obj == null) return;

            string normalizedKey = NormalizeKey(key);
            IObjectPool<T> pool = GetPool<T>(normalizedKey);

            // 检查对象是否在指定的池中
            bool isInActivePool = pool.IsObjectInActivePool(obj);

            if (isInActivePool)
            {
                // 对象在指定池中，直接释放
                pool.Release_Sync(obj);
            }
            else
            {
                bool isInPool = pool.IsObjectInPool(obj);
                Debug.LogError($"对象 {typeof(T).Name} 不在{key}关键字的活跃池中,是否已在静态池中{isInPool},本次释放无效");
            }
        }

        /// <summary>
        /// 异步释放对象（使用默认关键字，向后兼容）
        /// 如果对象不在默认池中，会自动查找对象所属的池并释放
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">要释放的对象</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async UniTask Release_Async<T>(T obj, CancellationToken cancellationToken = default)
        {
            if (obj == null) return;

            // 先尝试默认池
            string normalizedKey = NormalizeKey(DefaultKey);
            IObjectPool<T> pool = GetPool<T>(normalizedKey);

            // 检查对象是否在指定的池中
            bool isInActivePool = pool.IsObjectInActivePool(obj);

            if (isInActivePool)
            {
                // 对象在指定池中，直接释放
                await pool.Release_Async(obj, cancellationToken);
            }
            else
            {
                // 对象不在指定池中，尝试查找实际所属的池
                if (TryFindPoolForObject(obj, out var foundPool))
                {
                    await foundPool.Release_Async(obj, cancellationToken);
                }
                else
                {
                    Debug.LogError($"对象 {typeof(T).Name} 不在活跃池中，释放无效");
                }
            }
        }

        /// <summary>
        /// 异步释放对象（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="obj">要释放的对象</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async UniTask Release_Async<T>(string key, T obj, CancellationToken cancellationToken = default)
        {
            if (obj == null) return;

            string normalizedKey = NormalizeKey(key);
            IObjectPool<T> pool = GetPool<T>(normalizedKey);

            // 检查对象是否在指定的池中
            bool isInActivePool = pool.IsObjectInActivePool(obj);

            if (isInActivePool)
            {
                // 对象在指定池中，直接释放
                await pool.Release_Async(obj, cancellationToken);
            }
            else
            {
                bool isInPool = pool.IsObjectInPool(obj);
                Debug.LogError($"对象 {typeof(T).Name} 不在{key}关键字的活跃池中,是否已在静态池中{isInPool},本次释放无效");
            }
        }

        /// <summary>
        /// 批量获取对象（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="count">获取数量</param>
        /// <param name="priority">优先级</param>
        /// <returns>对象数组</returns>
        public T[] GetRange_Sync<T>(int count)
        {
            return GetRange_Sync<T>(DefaultKey, count);
        }

        /// <summary>
        /// 批量获取对象（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="count">获取数量</param>
        /// <param name="priority">优先级</param>
        /// <returns>对象数组</returns>
        public T[] GetRange_Sync<T>(string key, int count)
        {
            var pool = GetPool<T>(key);
            return pool.GetRange_Sync(count);
        }

        /// <summary>
        /// 批量释放对象（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="objects">要释放的对象集合</param>
        public void ReleaseRange_Sync<T>(List<T> objects)
        {
            ReleaseRange_Sync<T>(DefaultKey, objects);
        }

        /// <summary>
        /// 批量释放对象（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="objects">要释放的对象集合</param>
        public void ReleaseRange_Sync<T>(string key, List<T> objects)
        {
            var pool = GetPool<T>(key);
            pool.ReleaseRange_Sync(objects);
        }

        /// <summary>
        /// 批量获取对象（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="count">获取数量</param>
        /// <param name="priority">优先级</param>
        /// <returns>对象数组</returns>
        public async UniTask<T[]> GetRange_Async<T>(int count)
        {
            return await GetRange_Async<T>(DefaultKey, count);
        }

        /// <summary>
        /// 批量获取对象（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="count">获取数量</param>
        /// <param name="priority">优先级</param>
        /// <returns>对象数组</returns>
        public async UniTask<T[]> GetRange_Async<T>(string key, int count)
        {
            var pool = GetPool<T>(key);
            return await pool.GetRange_Async(count);
        }

        /// <summary>
        /// 批量释放对象（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="objects">要释放的对象集合</param>
        public async UniTask ReleaseRange_Async<T>(List<T> objects)
        {
            await ReleaseRange_Async<T>(DefaultKey, objects);
        }

        /// <summary>
        /// 批量释放对象（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="objects">要释放的对象集合</param>
        public async UniTask ReleaseRange_Async<T>(string key, List<T> objects)
        {
            var pool = GetPool<T>(key);
            await pool.ReleaseRange_Async(objects);
        }

        #endregion

        #region 池管理

        /// <summary>
        /// 获取对象池（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns>对象池</returns>
        public IObjectPool<T> GetPool<T>()
        {
            return GetPool<T>(DefaultKey);
        }

        /// <summary>
        /// 获取对象池（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <returns>对象池</returns>
        public IObjectPool<T> GetPool<T>(string key)
        {
            var type = typeof(T);
            var normalizedKey = NormalizeKey(key);
            if (!_pools.TryGetValue(type, out var keyPools))
            {
                //Debug.LogError($"对象池类型 {type.Name} 不存在");
                return null;
            }

            if (!keyPools.TryGetValue(normalizedKey, out var poolObj))
            {
                // 该关键字的池不存在
                //Debug.LogError($"对象池类型 {type.Name} 关键字 {normalizedKey} 不存在");
                return null;
            }

            return (IObjectPool<T>)poolObj;

        }

        /// <summary>
        /// 检查池是否存在（使用默认关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns>是否存在</returns>
        public bool HasPool<T>()
        {
            return HasPool<T>(DefaultKey);
        }

        /// <summary>
        /// 检查池是否存在（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <returns>是否存在</returns>
        public bool HasPool<T>(string key)
        {
            var type = typeof(T);
            var normalizedKey = NormalizeKey(key);
            return _pools.TryGetValue(type, out var keyPools) && keyPools.ContainsKey(normalizedKey);
        }

        /// <summary>
        /// 获取所有池的类型
        /// </summary>
        /// <returns>池类型列表</returns>
        public Type[] GetAllPoolTypes()
        {
            return _pools.Keys.ToArray();
        }

        /// <summary>
        /// 获取指定类型的所有关键字
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns>关键字列表</returns>
        public string[] GetPoolKeys<T>()
        {
            var type = typeof(T);
            if (_pools.TryGetValue(type, out var keyPools))
            {
                return keyPools.Keys.ToArray();
            }
            return new string[0];
        }

        /// <summary>
        /// 清理指定类型的池（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        public void ClearPool_Sync<T>()
        {
            ClearPool_Sync<T>(DefaultKey);
        }

        /// <summary>
        /// 清理指定类型的池（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        public void ClearPool_Sync<T>(string key)
        {
            var pool = GetPool<T>(key);
            pool.Clear_Sync();
        }

        /// <summary>
        /// 异步清理指定类型的池（使用默认关键字，向后兼容）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="cancellationToken">取消令牌</param>
        public async UniTask ClearPool_Async<T>(CancellationToken cancellationToken = default)
        {
            await ClearPool_Async<T>(DefaultKey, cancellationToken);
        }

        /// <summary>
        /// 异步清理指定类型的池（带关键字）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async UniTask ClearPool_Async<T>(string key, CancellationToken cancellationToken = default)
        {
            var pool = GetPool<T>(key);
            await pool.Clear_Async(cancellationToken);
        }

        /// <summary>
        /// 清理所有池
        /// </summary>
        public void ClearAll_Sync()
        {
            foreach (var keyPools in _pools.Values)
            {
                foreach (var poolObj in keyPools.Values)
                {
                    // 使用反射调用 Clear_Sync 方法（因为不知道具体的泛型类型）
                    var clearMethod = poolObj.GetType().GetMethod("Clear_Sync");
                    clearMethod?.Invoke(poolObj, null);
                }
            }
        }

        /// <summary>
        /// 异步清理所有池
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        public async UniTask ClearAll_Async(CancellationToken cancellationToken = default)
        {

            foreach (var keyPools in _pools.Values)
            {
                foreach (var poolObj in keyPools.Values)
                {
                    // 使用反射调用 Clear_Async 方法
                    var clearMethod = poolObj.GetType().GetMethod("Clear_Async");
                    if (clearMethod != null)
                    {
                        var task = clearMethod.Invoke(poolObj, new object[] { cancellationToken });
                        if (task is UniTask uniTask)
                        {
                            await uniTask;
                        }
                        else if (task is System.Threading.Tasks.Task taskObj)
                        {
                            await taskObj;
                        }
                    }
                }
            }

        }

        #endregion

        #region 关键字处理

        /// <summary>
        /// 规范化关键字：null转换为空字符串
        /// </summary>
        /// <param name="key">关键字</param>
        /// <returns>规范化后的关键字</returns>
        private string NormalizeKey(string key) => key ?? DefaultKey;

        /// <summary>
        /// 尝试查找对象所属的池
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">要查找的对象</param>
        /// <param name="foundPool">找到的池</param>
        /// <returns>是否找到</returns>
        private bool TryFindPoolForObject<T>(T obj, out IObjectPool<T> foundPool)
        {
            foundPool = null;

            if (obj == null) return false;

            // 遍历所有关键字池，查找对象所属的池
            //取出来_pools中所有的value然后遍历value，调用IsObjectInPool方法，如果返回true，则返回true，否则返回false
            foreach (var keyPool in _pools.Values)
            {
                foreach (var poolObj in keyPool.Values)
                {
                    if (poolObj is IObjectPool<T> pool && pool.IsObjectInActivePool(obj))
                    {
                        foundPool = pool;
                        return true;
                    }
                }
            }
            return false;
        }


        #endregion
    }
}